package com.tianlang.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.type.Type;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author mcp
 *
 * @param <T>
 */
@Transactional(readOnly = false, rollbackFor = Exception.class)
@SuppressWarnings("rawtypes")
public interface IBaseDao<T> {

	// Hibernate中的对象有3种状态：Transient（瞬时），Persistent（持久）和Detached（托管）。
	/**
	 * 持久化对象
	 * 
	 * @param entity
	 */
	public void save(final Object entity);

	/**
	 * 删除对象
	 * 
	 * @param entity
	 */
	public void delete(final Object entity);

	/**
	 * 删除单挑数据
	 * 
	 * @param clazz
	 * @param id
	 */
	public void delete(Class clazz, Serializable id);

	/**
	 * 删除数据
	 * @param hql
	 */
	public void delete(String hql);

	/****
	 * 删除数据
	 * 
	 * @param query
	 *            删除需要执行的HQL
	 * @param objects
	 *            执行HQL所需参数
	 * @param types
	 *            执行参数的参数类型
	 */
	public void delete(final String query, final Object[] objects, final Type[] types);

	/**
	 * 修改对象
	 * 
	 * @param entity
	 */
	public void update(final Object entity);

	/***
	 * 托管修改
	 * 
	 * @param entity
	 */
	public void saveMerge(Object entity);

	/****
	 * 保存或修改
	 * 
	 * @param entiry
	 */
	public void saveOrUpdate(final Object entiry);

	/**
	 * 保存或修改对象(多个)
	 * 
	 * @param c
	 */
	public void saveOrUpdateAll(Collection c);

	/**
	 * 获得对象
	 * @param entity
	 * @param id
	 * @return
	 */
	public Object load(final Class entity, final Serializable id);

	/**
	 * 加载全部对象 谨慎使用，将会加载整个表的数据
	 * 
	 * @param entity
	 * @return 整个表的数据
	 */
	public List findAll(final Class entity);

	/**
	 * 获得指定类型的所有数据 谨慎使用，将会加载整个表的数据
	 * 
	 * @param clazz
	 *            数据类型
	 * @return 结果集
	 */
	public List getObjects(Class clazz);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = 'abc']]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param namedQuery
	 *            预先定义的HQL名称
	 * @return 结果集
	 */

	public List findByNamedQuery(final String namedQuery);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = ?]]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 * @param parameter
	 *            查询参数
	 * @return 查询结果集
	 */
	public List findByNamedQuery(final String query, final Object parameter);

	/*****
	 * 查询预先定义好的HQL<br>
	 * eq: <br>
	 * hbm文件预先定义：<br>
	 * &lt;query name="byname"&gt;<br>
	 * &lt;![from User where u.name = ? and limit ?,?]]&gt;<br>
	 * &lt;/query&gt;<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 *            查询语句名
	 * @param parameters
	 *            查询参数
	 * @return 查询结果集
	 */
	public List findByNamedQuery(final String query, final Object[] parameters);

	/****
	 * 执行HQL语句<br>
	 * 
	 * @param query
	 *            HQL语句
	 * @return 查询结果集
	 */
	public List find(final String query);

	/**
	 * 获得单条数据
	 * 
	 * @param clazz
	 * @param id
	 * @return 结果集，未找到结果将获返回空
	 */
	public Object getObject(Class clazz, Serializable id);

	/****
	 * 执行HQL语句<br>
	 * 
	 * @param query
	 *            HQL语句
	 * @param parameter
	 * @return 查询结果集
	 */
	public List find(final String query, final Object parameter);

	/****
	 * 执行HQL语句<br>
	 * 注意限制查询结果集数量
	 * 
	 * @param query
	 *            HQL语句
	 * @param objects
	 *            查询参数
	 * @param types
	 *            查询参数类型
	 * @return 查询结果集
	 */
	public List find(final String query, final Object[] objects, final Type[] types);

	/******
	 * 执行HQL语句 注意限制查询结果集数量
	 * 
	 * @param query
	 *            HQL语句
	 * @param objects
	 *            查询参数
	 * @return
	 */
	public List find(final String query, final Object[] objects);

	/******
	 * 获得配置信息<br>
	 * 执行这样一个查询 select scd.paramvalue from Sysparam scd where scd.paramkey =:key
	 * 
	 * @param key
	 *            配置名
	 * @return 值
	 */
	public String getConfigurationValue(String key);

	/**
	 * 统计查询<br>
	 * 查询符合条件的数据条数 ，类似select count(*) where ...<br>
	 * eg: searchMap.put("username","xiaoming");<br>
	 * getTotalSize(User.class,searchMap);<br>
	 *            
	 * @param clz 查询类型
	 * @param searchMap 查询条件
	 * @param groupColumn
	 * @return
	 */

	public Integer getTotalSize(Class clz, Map<String, Object> searchMap, String groupColumn);

	/***
	 * 根据记录创建者查询<br>
	 * 指定数据创建者ID，获得创建者创建的所有数据。 谨慎使用，未限制结果集大小，你可能获得整个表的数据
	 * 
	 * @param clz
	 *            查询类型
	 * @param creatorId
	 *            创建者ID
	 * @param updateTime
	 *            修改时间
	 * @return 查询结果集
	 */

	public List getObjectByCreator(Class clz, Long creatorId, String updateTime);

	/***
	 * 根据记录创建者查询<br>
	 * 指定数据创建者ID，获得创建者创建的所有数据。 谨慎使用，未限制结果集大小，你可能获得整个表的数据
	 * 
	 * @param clz
	 *            查询类型
	 * @param creatorId
	 *            创建者ID
	 * @return 查询结果集
	 */
	public List getObjectByCreator(Class clz, Long creatorId);

	/*****
	 * 查询 谨慎使用，注意限制结果集大小<br>
	 * "本表查询条件"指在HQL中类似"username"这样不涉及别其他关联表的查询条件，
	 * "连接查询条件"指在HQL中类似"address.city"这样中间带点的查询条件，否则方法将不能正常获得查询结果，
	 * 并且对于“连接查询条件”不允许类似“user.address.city”两次连接的写法<br>
	 * 只会返回记过集的第一个对象，如果结果集不为空的话 eg: searchMap.put("username","abc");<br>
	 * getPaginationObjects(User.class,searchMap);<br>
	 * eg1:对于模糊查询你可以这样，<br>
	 * searchMap.put("username",Constants.LIKE+"abc");<br>
	 * getPaginationObjects(User.class,searchMap);<br>
	 * 
	 * @param clz
	 *            查询类型
	 * @param searchMap
	 *            本表查询条件
	 * @return 查询结果集第一个对象
	 */
	public Object getObjectByParams(Class clz, Map<String, Object> searchMap);

	/**
	 * 分页查询
	 * 
	 * @param where
	 * @param objects
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	public <E> List<E> getListByWhere(String where, Object[] objects, Integer pageIndex, Integer pageSize);

	/**
	 * 通过实体类例子分页查询
	 * 
	 * @param obj
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	public List<Object> findByExample(Object obj, Integer pageIndex, Integer pageSize);

	/**
	 * 总条数查询
	 * 
	 * @param where
	 * @param values
	 * @return
	 */
	public Object getCount(String where, Object[] values);

	/**
	 * 总条数查询
	 * @param where
	 * @param objects
	 * @return
	 */
	public Integer getTotalRecordCount(String where, Object[] objects);

	/**
	 * 总条数查询
	 * @param where
	 * @param cache
	 * @return
	 */
	public Integer getTotalRecordCount(final String where, final boolean cache);

	/**
	 * 分页查询【start=(pageIndex - 1) * pageSize】
	 * @param where
	 * @param objects
	 * @param start
	 * @param size
	 * @return
	 */
	public <E> List<E> getObjectsWhere(final String where, final Object[] objects, final Integer start,
			final Integer size);

	/////////////////////////////////// sql////////////////////////////////////////
	/**
	 * 原生sql分页查询
	 * 
	 * @param sql
	 * @param object
	 * @param pageIndexs
	 * @param pageSizes
	 * @param pojoClass
	 * @return
	 */
	public List<Object> querySQL(String sql, Object[] object, Integer pageIndexs, Integer pageSizes,
			Class<?> pojoClass);

	/**
	 * 分页查询
	 * 
	 * @param sql
	 * @param object
	 * @param pageIndexs
	 * @param pageSizes
	 * @param pojoClass
	 * @return Dto
	 */
	public List<Object> querySQLDto(String sql, Object[] object, Integer pageIndexs, Integer pageSizes,
			Class<?> pojoClass);

	/**
	 * 查询条数
	 * 
	 * @param sql
	 * @return 记录条数
	 */
	public Integer querySQLCount(String sql);

	/**
	 * 查询
	 * 
	 * @param sql
	 * @param object
	 * @param pojoClass
	 * @return
	 */
	public List<Object> querySQL(String sql, Object[] object, Class<?> pojoClass);

	/**
	 * 更新
	 * 
	 * @param sql
	 */
	public void executeSQL(final String sql);
}
